#include "Socket.hpp"
#include "Log.hpp"
#include "directory.hpp"
#include <sys/select.h>
#include <algorithm>
#include <memory>


using namespace Net_Work;

const static uint16_t defaultport = 8888;
const static int gbacklog = 8; // 维护的全连接队列
const static int num = sizeof(fd_set) * 8;

class selectServer
{
private:
    void HandlerEvent(fd_set rfds)
    {
        for (int i = 0; i < num; i++)
        {
            if (_rfds_array[i] == nullptr)
                continue;
            else
            {
                int fd = _rfds_array[i]->GetSockFd();
                if (FD_ISSET(fd, &rfds)) // 读事件就绪
                {
                    // 监听套接字上的读事件就绪
                    if (fd == _listensock->GetSockFd())
                    {
                        std::cout << "Get a new connection" << std::endl;
                        std::string clientip;
                        uint16_t clientport;
                        Socket *sock = _listensock->AcceptConnection(&clientip, &clientport);
                        if (!sock)
                        {
                            lg.LogMessage(Error, "accept failed\n");
                            continue;
                        }
                        int newfd = sock->GetSockFd();
                        lg.LogMessage(Info, "A new client, client info# %s:%d, fd: ", clientip.c_str(), clientport, newfd);

                        int pos = 0;
                        for (; pos < num; pos++)
                        {
                            if (_rfds_array[pos] == nullptr)
                            {
                                std::cout << "new connection's fd: " << newfd;
                                _rfds_array[pos] = sock;
                                break;
                            }
                        }
                        // 说明达到fd_set类型的上限
                        if (pos == num)
                        {
                            sock->CloseSocket();
                            delete sock;
                            std::cout << "full capacity!" << std::endl;
                        }
                    }
                    // 普通套接字上的读事件就绪
                    else
                    {
                        std::string buffer;
                        bool res = _rfds_array[i]->Recv(&buffer, 1024); // 接收数据

                        // 打印接收的结果
                        std::cout << "Recv result: " << res << std::endl;
                        std::cout << "Buffer length: " << buffer.length() << std::endl;                  // 打印实际长度
                        std::cout << "Buffer content before cleanup: \"" << buffer << "\"" << std::endl; // 打印原始内容

                        // 去掉 buffer 中的换行符和空格
                        // remove_if的作用是把空白字符移到最后面
                        buffer.erase(std::remove_if(buffer.begin(), buffer.end(), ::isspace), buffer.end());

                        std::cout << "Buffer after cleanup: \"" << buffer << "\"" << std::endl; // 打印清理后的 buffer

                        std::string meaning = gdir.translate(buffer); // 调用翻译
                        meaning += "\n";
                        // std::cout << "Meaning of buffer: " << meaning << std::endl;

                        if (res)
                        {
                            _rfds_array[i]->Send(meaning);
                        }
                        else
                        {
                            lg.LogMessage(Warning, "client quit, maybe close or error, close fd: %d\n", _rfds_array[i]->GetSockFd());
                            _rfds_array[i]->CloseSocket();
                            delete _rfds_array[i];
                            _rfds_array[i] = nullptr;
                        }
                    }
                }
            }
        }
    }

public:
    selectServer(uint16_t port = defaultport) : _port(port), _listensock(new TcpSocket()), _isrunning(false)
    {
    }

    void InitServer()
    {
        _listensock->BuildListenSocketMethod(_port, gbacklog);
        for (int i = 0; i < num; i++)
        {
            _rfds_array[i] = nullptr;
        }
        _rfds_array[0] = _listensock.get();
    }

    void Stop()
    {
        _isrunning = false;
    }

    void Loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            // 由于select使用的是输入输出型参数，每次循环我们要重置rfds
            fd_set rfds;
            FD_ZERO(&rfds);
            int max_fd = _listensock->GetSockFd();
            for (int i = 0; i < num; i++)
            {
                if (_rfds_array[i] == nullptr)
                    continue;
                else
                {
                    int fd = _rfds_array[i]->GetSockFd();
                    // 改的第一处
                    FD_SET(fd, &rfds); // 添加所有合法fd到rfds集合中
                    if (fd > max_fd)
                        max_fd = fd;
                }
            }

            struct timeval timeout = {0, 0};
            PrintDebug();
            int n = select(max_fd + 1, &rfds, nullptr, nullptr, /* timeout */ nullptr);
            switch (n)
            {
            case 0:
                lg.LogMessage(Info, "Select timeout, last time: %u.%u\n", timeout.tv_sec, timeout.tv_usec);
                break;
            case -1:
                lg.LogMessage(Warning, "Select failed\n");
                break;
            default:
                lg.LogMessage(Info, "Select success, last time: %u.%u\n", timeout.tv_sec, timeout.tv_usec);
                HandlerEvent(rfds);
                break;
            }
        }
        _isrunning = false;
    }
    void PrintDebug()
    {
        std::cout << "rfds list is:";
        for (int i = 0; i < num; i++)
        {
            if (_rfds_array[i] == nullptr)
                continue;
            else
            {
                std::cout << " " << _rfds_array[i]->GetSockFd();
            }
        }
    }

private:
    std::unique_ptr<Socket> _listensock;
    uint16_t _port;
    bool _isrunning;
    Directory gdir;

    Socket *_rfds_array[num];
};